home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / tutorials / custEducation / opengl2 / answers / superfly / superfly.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-11  |  29.7 KB  |  1,431 lines

  1. /* Copyright (c) Silicon Graphics, Inc. 1996 */
  2.  
  3. /*
  4.  * superfly.c 
  5.  * This program allows the user to "fly" through a simple virtual world. 
  6.  *
  7.  * Sample solution for opengl2 labs.
  8.  * Your challenge - make an even cooler fly!
  9.  *
  10.  * Utility routines are located in flyutil.c
  11.  *
  12.  * MODIFYING THE PROGRAM
  13.  * ---------------------
  14.  * New shapes should be added to the world in the routine
  15.  * drawShapes(). 
  16.  *
  17.  * If new shapes are to be on the path of the autopilot,
  18.  * they must be near a circle centered at the world 
  19.  * origin with a radius of 10.0, parallel to and
  20.  * raised above the 'floor,' the X-Z plane.
  21.  *
  22.  * As a starting point, here are some good places to center your
  23.  * objects:
  24.  *        ( 0.0, 1.0, 10.0  )
  25.  *        ( 7.0, 1.0, 7.0   )
  26.  *        ( 10.0, 1.0, 0.0  )
  27.  *        ( 7.0, 1.0, -7.0  )
  28.  *        ( 0.0, 1.0, -10.0 )
  29.  *        ( -7.0, 1.0, -7.0 )
  30.  *        ( -10.0, 1.0, 0.0 )
  31.  *        ( -7.0, 1.0, 7.0  )
  32.  *
  33.  *  Copyright 1991, 1992, 1993, 1994, 1995, 1996, Silicon Graphics,  Inc.
  34.  *  Technical Education Development
  35.  */
  36.  
  37.  
  38. /* fly.h contains function prototypes, and defines constants */
  39. #include <GL/gl.h>
  40. #include <GL/glu.h>
  41. #include <GL/glut.h>
  42.  
  43. #include "fly.h"  
  44. #include "rgbImageFile.h"  
  45.  
  46. /* function prototypes for functions added to original fly.c */
  47. GLvoid toggleRaster( GLvoid );
  48. GLvoid toggleTexture( GLvoid );
  49. GLvoid startPicking( int x, int y );
  50. GLvoid printHits (GLint hits, GLint, GLint, GLuint buffer[] );
  51. GLvoid cullingHits (GLint hits, GLuint buffer[] );
  52. GLvoid cullShapes( GLvoid );
  53. GLvoid drawSmallWorld( GLvoid );
  54. GLvoid toggleCulling( GLvoid );
  55. GLvoid cycleFog( GLvoid );
  56. GLvoid toggleMovingClip( GLvoid );
  57. GLvoid toggleMultisampling( GLvoid );
  58. GLvoid togglePolygonOffset( GLvoid );
  59. GLvoid toggleWaving( GLvoid );
  60. GLint  initTexgenList( char *imageFileName );
  61. GLint  initMipmapList( GLvoid );
  62. GLvoid initFlag( GLvoid );
  63. GLvoid drawFlag( GLvoid );
  64. GLvoid incDensity( GLvoid );
  65. GLvoid decDensity( GLvoid );
  66. GLvoid resetEye( GLvoid );
  67. GLuint nearestPower(GLuint value);
  68.  
  69. /* Global Variables */
  70.  
  71. static enum shapes { FLOOR, TETRA, CUBE, OCTA, DODECA, ICOSA, CONE, FLAG,
  72.              CYLINDER, SPHERE, TORUS, QUAD, FONT };
  73. static enum drawModes { WIREFRAME, SOLID, SIMPLE };
  74.  
  75. enum drawStyles { LIT_SMOOTH, LIT_FLAT, WIRE };
  76. enum clipModes { OFF, ATTACH_EYE, FIXED_IN_SCENE, MOVING };
  77.  
  78. static GLboolean pickedFlag[ TORUS + 1 ] = { GL_FALSE };
  79. static GLboolean visibleFlag[ TORUS + 1 ] = { GL_FALSE };
  80. static char *shapeNames[] = {  "floor", "tetra", "cube", "octa", "dodeca", 
  81.                 "icosa", "cone", "flag", "cylinder", "sphere", 
  82.                 "torus", "quad", "font" };
  83.  
  84. static GLdouble depthNormalizeFactor; 
  85. static GLdouble modelview[16], projection[16]; 
  86. static GLint   viewport[4];
  87.  
  88. static GLint     texgenList;
  89. static GLint     mipmapList;
  90.  
  91. extern GLboolean debugFlag;        /* print eye position info? */
  92. extern GLboolean lighting;
  93. extern GLboolean showGridFlag;
  94. extern GLboolean blendFlag;
  95.  
  96. static GLboolean clipMode = OFF;
  97.  
  98. extern GLint drawStyle;
  99. extern GLfloat ex, ey, ez;     /* eye position */
  100. extern GLfloat yaw;         /* eye rotation about y axis in degrees */
  101. extern GLfloat pitch;         /* eye rotation about x axis in degrees */
  102. extern GLfloat velocity;    /* eye velocity */
  103.  
  104. extern GLdouble znear, zfar;    /* z distance to near and far planes */
  105.  
  106. static unsigned int *image;
  107. static int imageWidth, imageHeight;
  108.  
  109. static GLboolean picking = GL_FALSE;
  110. static GLboolean culling = GL_FALSE;
  111. static GLboolean cullingFlag = GL_FALSE;    /* in culling mode? */
  112. static GLboolean calledRecursively = GL_FALSE;
  113. static GLboolean multisampleFlag = GL_FALSE;
  114. static GLboolean multisample_supported = GL_TRUE;
  115. static GLboolean polygonOffsetFlag = GL_FALSE;
  116. static GLboolean rasterFlag = GL_FALSE;
  117. static GLboolean textureFlag = GL_FALSE;
  118. static GLboolean waveFlag = GL_FALSE;
  119. static GLfloat      fogDensity = 0.05;
  120.  
  121. static GLfloat offsetscale = 0.5;
  122. static GLfloat offsetbias = 0.002;
  123.  
  124. static GLfloat ctlpoints[4][4][3];
  125.  
  126. #define BUFSIZE 1024
  127.  
  128. static GLuint outlineFont, filledFont;
  129.  
  130. #define STRING1    "Welcome to OpenGL"
  131. #define STRING2    "Programming 2!"
  132.  
  133. #define TEXFILE1    "tex1.rgb"
  134. #define TEXFILE2    "tex2.rgb"
  135.  
  136. GLvoid
  137. main( int argc, char *argv[] )
  138. {
  139.     GLdouble aspect;
  140.     GLsizei width, height;
  141.  
  142.     glutInit( &argc, argv );
  143.     
  144.     width = glutGet(GLUT_SCREEN_WIDTH); 
  145.     height = glutGet(GLUT_SCREEN_HEIGHT);
  146.     glutInitWindowPosition( width / 4, height / 4 );
  147.     glutInitWindowSize( width / 2, height / 2 );
  148. #ifdef GL_SGIS_multisample
  149.     glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE | GLUT_MULTISAMPLE );
  150. #else
  151.     glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
  152. #endif
  153.     glutCreateWindow( argv[0] );
  154.  
  155.     initgfx();
  156.  
  157.     glutIdleFunc( animate );
  158.     glutVisibilityFunc( visibility );
  159.     glutKeyboardFunc( keyboard );
  160.     glutSpecialFunc( specialkeys );
  161.     glutMouseFunc( mouse );
  162.     glutMotionFunc( motion );
  163.     glutReshapeFunc( reshape );
  164.     glutDisplayFunc( drawScene ); 
  165.  
  166.     printHelp( argv[0] );
  167.  
  168.     glutMainLoop();
  169. }
  170.  
  171. GLvoid
  172. printHelp( char *progname )
  173. {
  174.  
  175.     fprintf(stdout, "\n%s - fly through a simple virtual world.\n",
  176.         progname );
  177.     
  178.     printControls();
  179. }
  180.  
  181. GLvoid
  182. printControls( GLvoid )
  183. {
  184.     fprintf(stdout, "\n\n" 
  185.     "<?> key         - help, prints this info \n" 
  186.     "<a> key        - <a>utopilot start/stop \n"
  187.     "<b> key        - <b>lend, alpha blending \n"
  188.     "<c> key        - cycle <c>lipping plane modes \n"
  189.     "<d> key        - <d>ebug mode, prints coords \n"
  190.     "<f> key        - cycle <f>og modes\n"
  191.     "<g> key        - show floor <g>rid \n"
  192.     "<i> key        - <i>mage, displays raster image \n"
  193.     "<m> key        - <m>ultisampling toggle \n"
  194.     "<n> key        - <n>ormals drawing toggle \n"
  195.     "<p> key        - <p>olygon offset toggle \n"
  196.     "<r> key        - <r>eset eye position \n"
  197.     "<s> key        - <s>election culling \n"
  198.     "<t> key        - <t>exture mapping toggle \n"
  199.     "<w> key        - <w>aving flag toggle \n"
  200.     "SPACE key        - cycle wireframe/flat shaded/smooth \n"
  201.     "LEFT Mouse         - control moving the eye forward \n"
  202.     "MIDDLE Mouse         - control moving the eye backward \n"
  203.         "Mouse pointer   - change direction: pull back to go up, forward to dive\n"
  204.     "RIGHT Mouse        - pick a shape\n"
  205.     "UP Arrow Key        - increase the fog density\n"
  206.     "DOWN Arrow Key        - decrease the fog density\n"
  207.     "Escape key        - exit the program \n" );
  208. }
  209.  
  210. /*  Initialize material property, light source, and lighting model, 
  211.  */
  212. GLvoid
  213. initLighting( GLvoid )
  214. {
  215.     /* mat_specular and mat_shininess are NOT default values */
  216.     GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
  217.     GLfloat mat_shininess[] = { 10.0 };
  218.  
  219.     /* light_position is NOT default value */
  220.     GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
  221.  
  222.     glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
  223.     glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
  224.  
  225.     glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
  226.  
  227.     glLightfv(GL_LIGHT0, GL_POSITION, light_position);
  228.  
  229.     glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 1.0);
  230.  
  231.     glEnable(GL_LIGHTING);
  232.     glEnable(GL_LIGHT0);
  233. }
  234.  
  235. /*  Initializes the control points for the flag.
  236.  */
  237. GLvoid 
  238. initFlag(void)
  239. {
  240.     int s, t;
  241.     static GLdouble angle = 0.0;
  242.  
  243.     for (s = 0; s < 4; s++)
  244.     {
  245.         for (t = 0; t < 4; t++)
  246.         {
  247.             ctlpoints[s][t][0] = (double)s/2;
  248.             ctlpoints[s][t][1] = (double)t/2;
  249.             ctlpoints[s][t][2] = (double)s/2*sin(angle * (double)s);
  250.         }
  251.     }
  252.  
  253.     angle = fmodf (angle + 0.1, 360.0);
  254. }
  255.  
  256. GLvoid
  257. initgfx( GLvoid )
  258. {
  259.     glClearColor( 0.0, 0.0, 0.0, 1.0 );
  260.     glClearDepth( 1.0 );
  261.  
  262.     glClear( GL_COLOR_BUFFER_BIT );
  263.     glutSwapBuffers();
  264.  
  265.     glEnable( GL_DEPTH_TEST );
  266.  
  267.     initLighting();
  268.  
  269.     initFlag();
  270.  
  271.     /* depth values in hit record are
  272.      * multiplied by 2**32 - 1.
  273.      */
  274.     depthNormalizeFactor = pow(2, 32) - 1;
  275.  
  276.     resetEye();
  277.  
  278.     image = rgbReadImageFile("maxHeadroom.rgb", &imageWidth, &imageHeight);
  279.  
  280.     fprintf( stdout,  "\nLoading textures\n");
  281.     texgenList = initTexgenList( "flowers.rgb" );    
  282.     mipmapList = initMipmapList();    
  283.  
  284.     outlineFont = createOutlineFont();
  285.     filledFont = createFilledFont();
  286.  
  287.     if (!glutExtensionSupported("GL_EXT_polygon_offset")) {
  288.         printf( "GL_EXT_polygon_offset not supported by server\n");
  289.     }
  290. #ifdef GL_EXT_polygon_offset
  291.     glPolygonOffsetEXT( offsetscale, offsetbias );
  292. #endif
  293.  
  294.     if ( !glutExtensionSupported("GL_SGIS_multisample") ) {
  295.         printf( "GL_SGIS_multisample not supported by server\n");
  296.         multisample_supported = GL_FALSE;
  297.     }
  298.  
  299.     glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
  300. }
  301.  
  302. GLvoid 
  303. animate( GLvoid )
  304. {
  305.     if (!picking)
  306.         moveEye();
  307.  
  308.     /* Tell GLUT to redraw the scene */
  309.     glutPostRedisplay();
  310. }
  311.  
  312. GLvoid
  313. visibility( int state ) 
  314. {
  315.     if (state == GLUT_VISIBLE) {
  316.         glutIdleFunc( animate );
  317.     } else {
  318.         glutIdleFunc( NULL );
  319.     }
  320. }
  321.  
  322. /* Initialize the various input functions */
  323. GLvoid 
  324. keyboard( GLubyte key, GLint x, GLint y ) 
  325. {
  326.     /* all of the following routines are in flyutil.c */
  327.     switch (key) {
  328.     case ' ':
  329.         setDrawStyle();
  330.         break;
  331.     case 'a':
  332.         setAutopilot();
  333.         break;
  334.     case 'b':
  335.         toggleBlend();
  336.         break;
  337.     case 'd':
  338.         setDebug();
  339.         break;
  340.     case 'g':
  341.         toggleShowGrid();
  342.         break;
  343.     case 'n':
  344.         toggleDrawNormals();
  345.         break;
  346.     case 'r':
  347.         resetEye();
  348.         break;
  349.     case '?':
  350.     case '/':
  351.         printControls();
  352.         break;
  353.     /* new input functions */
  354.     case 'c':
  355.         toggleMovingClip();
  356.         break;
  357.     case 'f':
  358.         cycleFog();
  359.         break;
  360.     case 'i':
  361.         toggleRaster();
  362.         break;
  363.     case 'm':
  364.         toggleMultisampling();
  365.         break;
  366.     case 'p':
  367.         togglePolygonOffset();
  368.         break;
  369.     case 's':
  370.         toggleCulling();
  371.         break;
  372.     case 't':
  373.         toggleTexture();
  374.         break;
  375.     case 'w':
  376.         toggleWaving();
  377.         break;
  378.     case KEY_ESC:
  379.         exit(0);
  380.     }
  381.  
  382.     glutPostRedisplay();
  383. }
  384.  
  385. GLvoid
  386. specialkeys( GLint key, GLint x, GLint y )
  387. {
  388.     switch (key) {
  389.     case GLUT_KEY_UP:
  390.         incDensity();
  391.         break;
  392.     case GLUT_KEY_DOWN:
  393.         decDensity();
  394.         break;
  395.     }
  396.     glutPostRedisplay();
  397. }
  398.  
  399. GLvoid
  400. mouse( GLint button, GLint state, GLint x, GLint y )
  401. {
  402.     switch (button) {
  403.     case GLUT_LEFT_BUTTON:
  404.     case GLUT_MIDDLE_BUTTON:
  405.         if (state == GLUT_DOWN)
  406.             startMove(button, x, y);
  407.         else
  408.             stopMove();
  409.         glutPostRedisplay();
  410.         break;
  411.  
  412.     case GLUT_RIGHT_BUTTON:
  413.         if (state == GLUT_DOWN)
  414.             startPicking( x, y );
  415.         break;
  416.     }
  417. }
  418.  
  419. GLvoid
  420. motion( GLint x, GLint y )
  421. {
  422.     updatePosition( x, y );
  423.     glutPostRedisplay();
  424. }
  425.  
  426. GLvoid
  427. drawScene( GLvoid )
  428. {
  429.     static GLfloat floorDiffuse[] = { 0.5, 0.5, 0.0, 1.0 };
  430.  
  431.     GLdouble planeABCD[4] = {0.0, -1.0, 0.0, 1.5};
  432.     static GLfloat clipSpin = 0.0;
  433.  
  434.     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  435.  
  436.     glPushMatrix();
  437.  
  438.         if ( clipMode == ATTACH_EYE )
  439.         {
  440.             glClipPlane (GL_CLIP_PLANE1, planeABCD);
  441.         }
  442.  
  443.         /* accomplish a viewing transformation by moving
  444.          * the world relative to the eye
  445.          */
  446.         glRotatef( pitch, 1.0, 0.0, 0.0 );
  447.         glRotatef( yaw, 0.0, 1.0, 0.0 );
  448.         glTranslatef(-ex,-ey,-ez);
  449.  
  450.         if ( clipMode == FIXED_IN_SCENE )
  451.         {
  452.             glClipPlane (GL_CLIP_PLANE1, planeABCD);
  453.         }
  454.  
  455.         else if ( clipMode == MOVING )
  456.         {
  457.             glPushMatrix();
  458.                 glTranslatef( 0.0, sinf( clipSpin ), 0.0 ); 
  459.                 glClipPlane (GL_CLIP_PLANE1, planeABCD);
  460.                 clipSpin = fmodf( clipSpin + 0.1, 2*M_PI );
  461.             glPopMatrix();
  462.         }
  463.  
  464.         if ( clipMode )
  465.             glEnable (GL_CLIP_PLANE1);
  466.         else
  467.             glDisable (GL_CLIP_PLANE1);
  468.  
  469.         if ( rasterFlag )
  470.         {
  471.             static GLfloat rasterSpin = 0.0;
  472.             glPushMatrix();
  473.                 glRotatef( -rasterSpin, 0, 1, 0 );
  474.                 glTranslatef(9.0, 1.0, 0.0);
  475.                 glRasterPos3f( 0.0, 0.0, 0.0 );
  476.                 glDrawPixels (imageWidth, imageHeight, GL_RGBA, 
  477.                     GL_UNSIGNED_BYTE, image);
  478.             glPopMatrix();
  479.             rasterSpin = fmodf((rasterSpin + velocity*10.0), 360.0);
  480.         }
  481.     
  482.         if (lighting) {
  483.             glEnable( GL_LIGHTING );
  484.             glEnable( GL_COLOR_MATERIAL );
  485.         }
  486.  
  487.         glColor4fv( floorDiffuse );
  488.  
  489.         glPushMatrix();
  490.             if (picking)
  491.                 glLoadName(FLOOR);
  492.             else
  493.                     computeFloor(); /* function in flyutil.c */    
  494.             drawFloor();
  495.         glPopMatrix();
  496.  
  497.         if ( cullingFlag && !picking && inMotion() )
  498.             cullShapes();        
  499.  
  500.         drawShapes();
  501.  
  502.         if (lighting) {
  503.             glDisable( GL_COLOR_MATERIAL );
  504.             glDisable( GL_LIGHTING );
  505.         }
  506.  
  507.         if (picking)
  508.             glLoadName( FONT );
  509.  
  510.         /* draw some 3D text */
  511.         glPushMatrix();
  512.             glTranslatef(-10.1, -2.5, 10.1);
  513.             glScalef(0.1, 0.1, 0.1);
  514.             glColor4f( 1.0, 0.7, 0.0, 1.0 );
  515.             renderString( filledFont, STRING1 );
  516.         glPopMatrix();
  517.  
  518.         glPushMatrix();
  519.             glRotatef(90, 0, 1, 0);
  520.             glTranslatef(-9.9, -2.5, 10.1);
  521.             glScalef(0.1, 0.1, 0.1);
  522.             glColor4f( 0.6, 1, 0.8, 0.6 );
  523.             renderString( outlineFont, STRING2 );
  524.         glPopMatrix();
  525.     glPopMatrix();
  526.  
  527.     if ( !picking )
  528.         glutSwapBuffers();
  529.     else 
  530.         glFlush();
  531.     checkError("drawScene");
  532. }
  533.  
  534. GLvoid
  535. cullShapes( GLvoid )
  536. {
  537.     GLuint selectBuf[BUFSIZE];
  538.     GLint hits;
  539.     register int i;
  540.     
  541.     culling = GL_TRUE;
  542.     
  543.     glSelectBuffer (BUFSIZE, selectBuf);
  544.     (GLvoid) glRenderMode( GL_SELECT );
  545.         glInitNames();
  546.         glPushName( -1 );
  547.         /* set visibleFlags for all shapes */
  548.         for (i = 0; i < (TORUS+ 1); i++)
  549.             visibleFlag[i] = GL_TRUE;
  550.         drawShapes();    
  551.     hits = glRenderMode (GL_RENDER);
  552.     cullingHits (hits, selectBuf);    
  553.     culling = GL_FALSE;
  554.     /* Just in case cullingMode was turned off while in cullShapes,
  555.      * if no longer in culling mode, set visibleFlags for all shapes
  556.      */
  557.     if (!cullingFlag)
  558.     {
  559.         for (i = 0; i < (TORUS+ 1); i++)
  560.             visibleFlag[i] = GL_TRUE;
  561.     }
  562. }
  563.  
  564. GLvoid 
  565. cullingHits (GLint hits, GLuint buffer[] )
  566. {
  567.     register int i, j;
  568.     int names;
  569.     unsigned int *ptr;
  570.  
  571.     /* clear visibleFlags for all shapes */
  572.     for (i = 0; i < (TORUS+ 1); i++)
  573.         visibleFlag[i] = GL_FALSE;
  574.     
  575.     ptr = (unsigned int *) buffer;
  576.     if (debugFlag)
  577.         fprintf ( stdout, "culling hits = %d:  ", hits);
  578.     for (i = 0; i < hits; i++) 
  579.     {    /*  for each hit  */
  580.         names = *ptr;
  581.         ptr += 3; /* skip z1 and z2 */
  582.         for (j = 0; j < names; j++) 
  583.         {    /*  for each name */
  584.             if (*ptr < (TORUS + 1))
  585.             {
  586.                 if (debugFlag)
  587.                     fprintf(stdout, "%s ", shapeNames[*ptr]);
  588.                 visibleFlag[*ptr] = GL_TRUE;
  589.             }
  590.             ptr++;
  591.         }
  592.     }
  593.     if (debugFlag)
  594.         fprintf ( stdout, "\n\n");
  595. }
  596.  
  597.  
  598.  
  599. GLvoid
  600. drawShapes( GLvoid )
  601. {
  602.     GLfloat shapesDiffuseAlpha[] = { 0.5, 0.1, 0.8, 0.3 };
  603.  
  604.     glColor3f( 0.1, 0.4, 0.5 );
  605.     drawMovedShape( TETRA, -5.0, 1.0, 8.7 ); 
  606.     glColor3f( 0.2, 0.5, 0.0 );
  607.     drawMovedShape( CUBE, -8.7, 1.0, 0.5 );
  608.     glColor3f( 0.3, 0.6, 1.0 );
  609.     drawMovedShape( OCTA, 5.0, 1.0, 8.7 );
  610.     glColor3f( 0.4, 0.7, 0.0 );
  611.     drawMovedShape( DODECA, -8.7, 1.0, -5.0 );
  612.     glColor3f( 0.5, 0.8, 1.0 );
  613.     drawMovedShape( ICOSA, -5.0, 1.0, -8.7 );
  614.     glColor3f( 0.6, 0.9, 0.0 );
  615.     drawMovedShape( CONE, 8.7, 1.0, 5.0 );
  616.  
  617.     /* draw a flag at the top of the cone */
  618.     if (picking)
  619.         glLoadName(FLAG);
  620.  
  621.     glColor3f( 0.6, 0.9, 1.0 );
  622.     glPushMatrix();
  623.         glTranslatef( 8.7,3.0,5.0 );
  624.         drawFlag();
  625.     glPopMatrix();
  626.  
  627.     glColor4fv( shapesDiffuseAlpha );
  628.  
  629.     if ( !culling && !calledRecursively && drawStyle != WIRE)
  630.     {
  631.         if ( textureFlag )
  632.         {
  633.             glEnable(GL_TEXTURE_2D);
  634.             if (lighting) {
  635.                 glDisable(GL_COLOR_MATERIAL);
  636.                 glDisable(GL_LIGHTING);
  637.             }
  638.             glColor4f(1, 1, 1, 0.3);
  639.  
  640.             /* draw a textured quad using 
  641.              * explicit texture coordinates
  642.              */
  643.             if (picking)
  644.                 glLoadName(QUAD);
  645.  
  646.             glCallList(mipmapList);
  647.             drawTexturedQuad();
  648.  
  649.             /* switch to automatic texture 
  650.              * coordinate generation
  651.              */
  652.             glEnable(GL_TEXTURE_GEN_S);
  653.             glEnable(GL_TEXTURE_GEN_T);
  654.  
  655.             glCallList(texgenList);
  656.         }
  657.     }
  658.  
  659.  
  660.     if ( blendFlag && drawStyle != WIRE )
  661.         enableBlending();
  662.     drawMovedShape( CYLINDER, 10.0, 1.5, 0.0 );
  663.     drawMovedShape( SPHERE, 7.0, 2.0, -7.0 );
  664.     drawMovedShape( TORUS, 0.0, 2.0, -10.0 );
  665.     if ( blendFlag && drawStyle != WIRE )
  666.         disableBlending();
  667.  
  668.     if ( !culling && !calledRecursively && drawStyle != WIRE)
  669.     {
  670.         if ( textureFlag )
  671.         {
  672.             glDisable(GL_TEXTURE_GEN_S);
  673.             glDisable(GL_TEXTURE_GEN_T);
  674.             glDisable(GL_TEXTURE_2D);
  675.             if (lighting) {
  676.                 glEnable(GL_COLOR_MATERIAL);
  677.                 glEnable(GL_LIGHTING);
  678.             }
  679.         }
  680.     }
  681. }
  682.  
  683. GLvoid
  684. drawMovedShape( GLint currentShape, GLfloat x, GLfloat y, GLfloat z )
  685. {
  686.     if ( !visibleFlag[currentShape] && !calledRecursively )
  687.     {
  688.         ;  /* if not visible and not called recursively, don't draw */
  689.     }
  690.     else
  691.     {
  692.         glPushMatrix();
  693.         glTranslatef(x, y, z);
  694.         if (culling)
  695.         {
  696.             drawShape( currentShape, SIMPLE );
  697.         }
  698.         else if ((drawStyle == WIRE || pickedFlag[currentShape] ) && 
  699.             (!picking)) 
  700.         {
  701.             if ( pickedFlag[currentShape] && !calledRecursively )
  702.                 drawSmallWorld();
  703.             drawShape( currentShape, WIREFRAME );
  704.         }
  705.         else
  706.         {
  707.             drawShape( currentShape, SOLID );
  708.         }
  709.         glPopMatrix();
  710.     }
  711. }
  712.  
  713. GLvoid
  714. drawShape( GLint currentShape, GLint drawMode )
  715. {
  716.     if (picking) glLoadName(currentShape);
  717.     switch( currentShape )
  718.     {
  719.         case TETRA:
  720.             drawTetra( drawMode );
  721.             break;
  722.         case CUBE:
  723.             drawCube( drawMode );
  724.             break;
  725.         case OCTA:
  726.             drawOcta( drawMode );
  727.             break;
  728.         case DODECA:
  729.             drawDodeca( drawMode );
  730.             break;
  731.         case ICOSA:
  732.             drawIcosa( drawMode );
  733.             break;
  734.         case CONE:
  735.             drawCone( drawMode );
  736.             break;
  737.         case CYLINDER:
  738.             drawCylinder( drawMode );
  739.             break;
  740.         case SPHERE:
  741.             drawSphere( drawMode );
  742.             break;
  743.         case TORUS:
  744.             drawTorus( drawMode );
  745.             break;
  746.         default:
  747.             break;
  748.     }
  749. }
  750.         
  751. GLvoid
  752. drawTetra( GLint drawMode )
  753. {            
  754.     switch( drawMode )
  755.     {
  756.         case WIREFRAME:
  757.             glutWireTetrahedron( );
  758.             break;
  759.         case SOLID:
  760.         case SIMPLE:
  761.             glutSolidTetrahedron( );
  762.             break;
  763.         default:
  764.             break;
  765.     }
  766. }                    
  767.  
  768. GLvoid
  769. drawCube( GLint drawMode )
  770. {            
  771.     switch( drawMode )
  772.     {
  773.         case WIREFRAME:
  774.             glutWireCube( 1.0 );
  775.             break;
  776.         case SOLID:
  777.         case SIMPLE:
  778.             glutSolidCube( 1.0 );
  779.             break;
  780.         default:
  781.             break;
  782.     }
  783. }                    
  784.  
  785. GLvoid
  786. drawOcta( GLint drawMode )
  787. {            
  788.     switch( drawMode )
  789.     {
  790.         case WIREFRAME:
  791.             glutWireOctahedron( );
  792.             break;
  793.         case SOLID:
  794.         case SIMPLE:
  795.             glutSolidOctahedron( );
  796.             break;
  797.         default:
  798.             break;
  799.     }
  800. }                    
  801.  
  802.  
  803. GLvoid
  804. drawDodeca( GLint drawMode )
  805. {            
  806.     switch( drawMode )
  807.     {
  808.         case WIREFRAME:
  809.             glutWireDodecahedron( );
  810.             break;
  811.         case SOLID:
  812.         case SIMPLE:
  813.             glutSolidDodecahedron( );
  814.             break;
  815.         default:
  816.             break;
  817.     }
  818. }                    
  819.  
  820. GLvoid
  821. drawIcosa( GLint drawMode )
  822. {            
  823.     switch( drawMode )
  824.     {
  825.         case WIREFRAME:
  826.             glutWireIcosahedron( );
  827.             break;
  828.         case SOLID:
  829.         case SIMPLE:
  830.             glutSolidIcosahedron(  );
  831.             break;
  832.         default:
  833.             break;
  834.     }
  835. }                    
  836.  
  837. GLvoid
  838. drawCone( GLint drawMode )
  839. {            
  840.     glRotatef(-90.0, 1.0, 0.0, 0.0);
  841.     switch( drawMode )
  842.     {
  843.         case WIREFRAME:
  844.             glutWireCone( 1.0, 2.0, 8, 15 );
  845.             break;
  846.         case SOLID:
  847.         case SIMPLE:
  848.             glutSolidCone( 1.0, 2.0, 8, 15 );
  849.             break;
  850.         default:
  851.             break;
  852.     }
  853. }                    
  854.  
  855. GLvoid
  856. drawCylinder( GLint drawMode )
  857. {            
  858.     glRotatef(90.0, 1.0, 0.0, 0.0);
  859.     switch( drawMode )
  860.     {
  861.         case WIREFRAME:
  862.             WireCylinder( 1.0, 2.0 );
  863.             break;
  864.         case SOLID:
  865.         case SIMPLE:
  866.             SolidCylinder( 1.0, 2.0 );
  867.             break;
  868.         default:
  869.             break;
  870.     }
  871. }                    
  872.  
  873. GLvoid
  874. drawSphere( GLint drawMode )
  875. {            
  876.     switch( drawMode )
  877.     {
  878.         case WIREFRAME:
  879.             glutWireSphere( 1.0, 15, 31 );
  880.             break;
  881.         case SOLID:
  882.             glutSolidSphere( 1.0, 15, 31 );
  883.             break;
  884.         case SIMPLE:
  885.             glutSolidIcosahedron( );
  886.             break;
  887.         default:
  888.             break;
  889.     }
  890. }                    
  891.  
  892. GLvoid
  893. drawTorus( GLint drawMode )
  894. {            
  895.     static GLint spinTorus = 0;
  896.     
  897.     glRotatef( (GLfloat)spinTorus, 0.0, 1.0, 0.0 );
  898.     switch( drawMode )
  899.     {
  900.         case WIREFRAME:
  901.             glutWireTorus( 0.25, 0.75, 15, 31 );
  902.             break;
  903.         case SOLID:
  904.             glutSolidTorus( 0.25, 0.75, 15, 31 );
  905.             break;
  906.         case SIMPLE:
  907.             SolidBox ( 2.0, 2.0, 0.5 );
  908.             break;
  909.         default:
  910.             break;
  911.     }
  912.     if ( !picking && !culling && !calledRecursively )
  913.         spinTorus = ( spinTorus + (int)(20*velocity) ) % 360;
  914. }
  915.  
  916. GLvoid 
  917. drawSmallWorld( GLvoid )
  918. {
  919.     calledRecursively = GL_TRUE;
  920.     /* need this because of the glScalef call */
  921.     glEnable( GL_NORMALIZE );
  922.  
  923.     glPushMatrix();
  924.         glScalef(0.075, 0.075, 0.075);
  925.         drawShapes();
  926.     glPopMatrix();
  927.     glDisable( GL_NORMALIZE );
  928.     calledRecursively = GL_FALSE;
  929. }
  930.  
  931. GLvoid
  932. drawFloor( GLvoid )
  933. {
  934.         GLfloat gridDiffuse[] = { 0.5, 0.5, 0.0, 1.0 };
  935.         GLfloat surfaceDiffuse[] = { 0.05, 0.15, 1.0, 1.0 };
  936.  
  937. #ifdef GL_EXT_polygon_offset
  938.         if ( polygonOffsetFlag == GL_TRUE )
  939.                 glEnable(GL_POLYGON_OFFSET_EXT);
  940. #endif
  941.  
  942.         if ( drawStyle != WIRE ) {
  943.         glColor4fv( surfaceDiffuse );
  944.         drawFloorFilled();
  945.     }
  946.  
  947.         if ( drawStyle == WIRE || showGridFlag == GL_TRUE ) {
  948.         glColor4fv( gridDiffuse );
  949.         drawFloorWire();
  950.     }
  951.  
  952. #ifdef GL_EXT_polygon_offset
  953.         if ( polygonOffsetFlag == GL_TRUE )
  954.                 glDisable(GL_POLYGON_OFFSET_EXT);
  955. #endif
  956. }
  957.  
  958. GLvoid
  959. makeFlag( GLUnurbsObj *theNurb )
  960. {
  961.     GLfloat flagDiffuse[] = { 0.8, 0.8, 0.2, 1.0 };
  962.  
  963.     GLfloat knots[8] = {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0};
  964.     GLfloat edgePts[5][2] = /* counter clockwise */
  965.         {{0.0, 0.0}, {1.0, 0.0}, {1.0, 1.0}, {0.0, 1.0}, {0.0, 0.0}};
  966.  
  967.     GLfloat curveKnots[8] = {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0};
  968.     /* curvePts and PwlPt are specified in a clockwise order so
  969.      * as to cut a hole in the surface 
  970.      */
  971.     GLfloat curvePts[4][2] = {{0.1,0.5}, {0.1,0.9}, {0.9,0.9}, {0.9,0.5}};
  972.     GLfloat pwlPts[4][2] = {{0.9,0.5}, {0.5,0.1}, {0.1,0.5}};
  973.  
  974.     /* an upwards spiraling nurbs curve */
  975.     GLfloat polePts[4][3] =
  976.         {{0.0,0.0,0.0}, {1.0,0.25,0.0}, {-1.0,0.75,0.0}, {0.0,1.0,0.0}};
  977.  
  978.     glColor4fv( flagDiffuse );
  979.  
  980.     /* draw the flag pole */
  981.     gluBeginCurve(theNurb);
  982.         gluNurbsCurve (theNurb, 8, curveKnots, 3, 
  983.             &polePts[0][0], 4, GL_MAP1_VERTEX_3);
  984.     gluEndCurve(theNurb);
  985.  
  986.     /* draw the flag on top of the pole */
  987.     glPushMatrix();
  988.         glTranslatef(0.0, 1.0, 0.0);
  989.         gluBeginSurface(theNurb);
  990.             gluNurbsSurface(theNurb, 
  991.                     8, knots,
  992.                     8, knots,
  993.                     4 * 3, 3,
  994.                     &ctlpoints[0][0][0], 
  995.                     4, 4,
  996.                     GL_MAP2_VERTEX_3);
  997.  
  998.             gluBeginTrim(theNurb);
  999.                 gluPwlCurve(theNurb, 5, &edgePts[0][0], 2,
  1000.                 GLU_MAP1_TRIM_2);
  1001.             gluEndTrim(theNurb);
  1002.  
  1003.             gluBeginTrim(theNurb);
  1004.                 gluNurbsCurve(theNurb, 8, curveKnots, 2, 
  1005.                     &curvePts[0][0], 4, GLU_MAP1_TRIM_2);
  1006.                 gluPwlCurve(theNurb, 3, &pwlPts[0][0], 2, 
  1007.                     GLU_MAP1_TRIM_2);
  1008.             gluEndTrim(theNurb);
  1009.         gluEndSurface(theNurb);
  1010.     glPopMatrix();
  1011. }
  1012.  
  1013. /* Draw a NURBS surface with a half-oval cut out of it */
  1014. GLvoid
  1015. drawFlag( GLvoid )
  1016. {
  1017.     static int first = 1;
  1018.     static GLint flagList;
  1019.     static GLUnurbsObj *theNurb = NULL;
  1020.  
  1021.     if (first) {
  1022.         GLfloat modelView[16], Projection[16]; 
  1023.  
  1024.         /* Save the current matrices to be loaded with the
  1025.          * display listed objects.  The objects will all be 
  1026.          * tessellated using these matrices.
  1027.          */
  1028.         glGetFloatv(GL_MODELVIEW_MATRIX, modelView);
  1029.         glGetFloatv(GL_PROJECTION_MATRIX, Projection);
  1030.         glGetIntegerv(GL_VIEWPORT, viewport);
  1031.  
  1032.         /* Turn off automatic loading of matrices and set up 
  1033.          * sampling matrices to be used when display list is 
  1034.          * created
  1035.          */
  1036.         theNurb = gluNewNurbsRenderer();
  1037.         gluNurbsProperty(theNurb, GLU_SAMPLING_TOLERANCE, 10.0);
  1038.         gluNurbsProperty(theNurb, GLU_AUTO_LOAD_MATRIX, GL_FALSE);
  1039.         gluLoadSamplingMatrices(theNurb, modelView, Projection,
  1040.                 viewport);
  1041.  
  1042.         /* create display list */
  1043.         flagList = glGenLists(1);
  1044.         glNewList(flagList, GL_COMPILE_AND_EXECUTE);
  1045.             makeFlag( theNurb );
  1046.         glEndList();
  1047.         first = 0;
  1048.     } else if (waveFlag) {
  1049.         initFlag();
  1050.         makeFlag( theNurb );
  1051.     } else {
  1052.         /* if not waving and the display list exists, use it */
  1053.         glCallList( flagList );
  1054.     }
  1055. }
  1056.  
  1057. drawTexturedQuad( GLvoid )
  1058. {
  1059.     float v0[3] = { -1.0, -1.0, 0.0};
  1060.     float v1[3] = {1.0, -1.0, 0.0};
  1061.     float v2[3] = {1.0, 1.0, 0.0};
  1062.     float v3[3] = { -1.0, 1.0, 0.0};
  1063.  
  1064.     float t0[3] = {0.0, 0.0};
  1065.     float t1[3] = {1.0, 0.0};
  1066.     float t2[3] = {1.0, 1.0};
  1067.     float t3[3] = {0.0, 1.0};
  1068.  
  1069.     float n0[3] = {0, 0, 1};
  1070.  
  1071.     static GLdouble angle = 0.0;
  1072.  
  1073.     glPushMatrix();
  1074.         glTranslatef(0, 3, 0);
  1075.         glRotatef(angle, 0, 1, 0);
  1076.  
  1077.         glBegin(GL_QUADS);
  1078.             glNormal3fv(n0);
  1079.             glTexCoord2fv(t0); glVertex3fv(v0);
  1080.             glTexCoord2fv(t1); glVertex3fv(v1);
  1081.             glTexCoord2fv(t2); glVertex3fv(v2);
  1082.             glTexCoord2fv(t3); glVertex3fv(v3);
  1083.         glEnd();
  1084.  
  1085.     glPopMatrix();
  1086.  
  1087.     angle = fmodf(angle + 5.0, 360.0);
  1088. }
  1089.  
  1090. GLvoid
  1091. toggleRaster( GLvoid )
  1092. {
  1093.     rasterFlag = !rasterFlag;
  1094. }
  1095.  
  1096. GLvoid
  1097. toggleMultisampling( GLvoid )
  1098. {
  1099.     if (multisample_supported) {
  1100. #ifdef GL_SGIS_multisample
  1101.         /* Toggle polygon offset */
  1102.         multisampleFlag = !multisampleFlag;
  1103.         if ( multisampleFlag ) 
  1104.             glEnable( GL_MULTISAMPLE_SGIS );
  1105.         else 
  1106.             glDisable( GL_MULTISAMPLE_SGIS );
  1107.         fprintf( stdout, "multisampleFlag = %d\n", multisampleFlag );
  1108. #endif
  1109.     } else {
  1110.         printf( "GL_SGIS_multisample not supported by server\n");
  1111.     }
  1112. }
  1113.  
  1114. GLvoid
  1115. togglePolygonOffset( GLvoid )
  1116. {
  1117. #ifdef GL_EXT_polygon_offset
  1118.     /* Toggle polygon offset */
  1119.     polygonOffsetFlag = !polygonOffsetFlag;
  1120. #endif
  1121.     fprintf( stdout, "polygonOffsetFlag = %d\n", polygonOffsetFlag );
  1122. }
  1123.  
  1124. GLvoid
  1125. toggleTexture( GLvoid )
  1126. {
  1127.     textureFlag = !textureFlag;
  1128.     fprintf( stdout, "textureFlag = %d\n", textureFlag );
  1129. }
  1130.  
  1131. GLvoid
  1132. toggleWaving( GLvoid )
  1133. {
  1134.     waveFlag = !waveFlag;
  1135.     fprintf( stdout, "waveFlag = %d\n", waveFlag );
  1136. }
  1137.  
  1138. GLvoid
  1139. cycleFog( GLvoid )
  1140. {
  1141.     GLfloat fogColor[] = { 0.5, 0.5, 0.5, 1.0 };
  1142.     static  GLint    fogMode = 0;
  1143.  
  1144.     fogMode = ++fogMode % 4;
  1145.  
  1146.     switch (fogMode) {
  1147.     case 0:
  1148.         glClearColor( 0.0, 0.0, 0.0, 1.0 );
  1149.         glDisable( GL_FOG );        
  1150.         break;
  1151.     case 1: 
  1152.         glFogi( GL_FOG_MODE, GL_EXP2 );
  1153.         printf( "Fog mode is GL_EXP2\n" );
  1154.         break;
  1155.     case 2:
  1156.         glFogi( GL_FOG_MODE, GL_EXP );
  1157.         printf( "Fog mode is GL_EXP\n" );
  1158.         break;
  1159.     case 3:
  1160.         glFogi( GL_FOG_MODE, GL_LINEAR );
  1161.         glFogf( GL_FOG_START, 20.0 );
  1162.         glFogf( GL_FOG_END, 40.0 );
  1163.         printf( "Fog mode is GL_LINEAR: start = 20.0, end = 40.0\n" );
  1164.         break;
  1165.     }
  1166.  
  1167.     if ( fogMode != 0 )
  1168.     {
  1169.         glClearColor( fogColor[0], fogColor[1], fogColor[2], 
  1170.             fogColor[3] );
  1171.         glFogfv( GL_FOG_COLOR, fogColor );
  1172.         glFogf( GL_FOG_DENSITY, fogDensity );
  1173.         glEnable( GL_FOG );        
  1174.     }
  1175.  
  1176. }
  1177.  
  1178. GLvoid
  1179. decDensity( GLvoid )
  1180. {
  1181.     fogDensity -= 0.01;
  1182.     if (fogDensity < 0.0)
  1183.     fogDensity = 0.0;
  1184.  
  1185.     glFogf (GL_FOG_DENSITY, fogDensity);
  1186.     printf ("Fog density = %4.2f\n", fogDensity);
  1187. }
  1188.  
  1189. GLvoid
  1190. incDensity( GLvoid )
  1191. {
  1192.     fogDensity += 0.01;
  1193.     if (fogDensity > 1.0)
  1194.     fogDensity = 1.0;
  1195.  
  1196.     glFogf (GL_FOG_DENSITY, fogDensity);
  1197.     printf ("Fog density = %4.2f\n", fogDensity);
  1198. }
  1199.  
  1200. GLvoid
  1201. toggleMovingClip( GLvoid )
  1202. {
  1203.     /* OFF, ATTACH_EYE, FIXED_IN_SCENE, MOVING */
  1204.     
  1205.     clipMode++;
  1206.     if ( clipMode > MOVING )
  1207.         clipMode = OFF;
  1208.     
  1209.     switch( clipMode )
  1210.     {
  1211.         case OFF:
  1212.             fprintf( stdout, "clipMode = OFF\n" );
  1213.             break;
  1214.         case ATTACH_EYE:
  1215.             fprintf( stdout, "clipMode = ATTACH_EYE\n" );
  1216.             break;
  1217.         case FIXED_IN_SCENE:
  1218.             fprintf( stdout, "clipMode = FIXED_IN_SCENE\n" );
  1219.             break;
  1220.         case MOVING:
  1221.             fprintf( stdout, "clipMode = MOVING\n" );
  1222.             break;
  1223.         default:
  1224.             break;
  1225.     }
  1226. }
  1227.  
  1228.  
  1229. GLvoid
  1230. toggleCulling( GLvoid )
  1231. {
  1232.     register int i;
  1233.     
  1234.     cullingFlag = !cullingFlag;
  1235.     fprintf( stdout, "cullingFlag = %d\n", cullingFlag ); 
  1236.     /* set visibleFlags for all shapes */
  1237.     for (i = 0; i < (TORUS+ 1); i++)
  1238.         visibleFlag[i] = GL_TRUE;
  1239. }
  1240.  
  1241. GLvoid  
  1242. startPicking( GLint mouseX, GLint mouseY )
  1243. {
  1244.     GLuint selectBuf[BUFSIZE];
  1245.     GLint hits;
  1246.     GLint viewport[4];
  1247.     GLdouble aspect;
  1248.  
  1249.     picking = GL_TRUE;
  1250.     glGetIntegerv (GL_VIEWPORT, viewport);
  1251.     glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
  1252.     glGetDoublev( GL_PROJECTION_MATRIX, projection );
  1253.     aspect = (GLdouble) viewport[2] / (GLdouble) viewport[3];
  1254.     
  1255.     glSelectBuffer (BUFSIZE, selectBuf);
  1256.     (GLvoid) glRenderMode( GL_SELECT );
  1257.     glInitNames();
  1258.     glPushName( -1 );
  1259.     glMatrixMode( GL_PROJECTION );
  1260.     glPushMatrix();
  1261.         glLoadIdentity();
  1262.         gluPickMatrix( (GLdouble) mouseX, 
  1263.             (GLdouble) (viewport[3] - mouseY), 
  1264.             5, 5,  /* x, y pixel tolerance for pick */
  1265.             viewport );
  1266.         gluPerspective( 45.0, aspect, znear, zfar );
  1267.         glMatrixMode( GL_MODELVIEW );
  1268.         drawScene();
  1269.         hits = glRenderMode (GL_RENDER);
  1270.         printHits (hits, mouseX, viewport[3] - mouseY, selectBuf);    
  1271.         picking = GL_FALSE;
  1272.         glMatrixMode( GL_PROJECTION );
  1273.     glPopMatrix();
  1274.     glMatrixMode( GL_MODELVIEW );
  1275. }
  1276.  
  1277. GLvoid 
  1278. printHits (GLint hits, GLint winx, GLint winy, GLuint buffer[] )
  1279. {
  1280.     unsigned int i, j, names, ii, jj;
  1281.     unsigned int *ptr;
  1282.     GLdouble min_depth, max_depth, objx, objy, objz;
  1283.     
  1284.     printf ("hits = %d\n", hits);
  1285.     ptr = (unsigned int *) buffer;
  1286.     for (i = 0; i < hits; i++) 
  1287.     {    /*  for each hit  */
  1288.         names = *ptr; ptr++;
  1289.  
  1290.         min_depth = ((GLdouble)(*ptr)/depthNormalizeFactor); ptr++;
  1291.         gluUnProject( winx, winy, min_depth, modelview, projection, 
  1292.                 viewport, &objx, &objy, &objz);
  1293.         printf( " z1 = %f", objz );
  1294.  
  1295.         max_depth = ((GLdouble)(*ptr)/depthNormalizeFactor); ptr++;
  1296.         gluUnProject( winx, winy, max_depth, modelview, projection, 
  1297.                 viewport, &objx, &objy, &objz);
  1298.         printf( " z2 = %f\n", objz );
  1299.  
  1300.         printf ("\tHit name:");
  1301.         for (j = 0; j < names; j++) 
  1302.         {    /*  for each name */
  1303.             if (*ptr < (TORUS + 1))
  1304.             {
  1305.                 fprintf (stdout, 
  1306.                     "  %s", shapeNames[*ptr] );
  1307.                 pickedFlag[*ptr] = !pickedFlag[*ptr];
  1308.             }
  1309.             ptr++;
  1310.         }
  1311.     printf ("\n\n");
  1312.     }
  1313. }
  1314.  
  1315. GLuint nearestPower(GLuint value)
  1316. {
  1317.     int i = 1;
  1318.  
  1319.     if (value == 0)
  1320.         return - 1;                     /* Error! */
  1321.     for (;;)
  1322.     {
  1323.         if (value == 1)
  1324.                 return i;
  1325.         else if (value == 3)
  1326.             return i *4;
  1327.         value >>= 1;
  1328.         i *= 2;
  1329.     }
  1330. }
  1331.  
  1332. /* Automatically build mipmaps */
  1333.  
  1334. GLint initTexgenList( char *imageFileName )
  1335. {
  1336.     GLuint texList;
  1337.     int texWidth, texHeight;
  1338.     GLuint *textureImage;
  1339.  
  1340.     textureImage = rgbReadImageFile(imageFileName, &texWidth, &texHeight);
  1341.  
  1342.     texList = glGenLists(1);
  1343.     glNewList(texList, GL_COMPILE);
  1344.  
  1345.     /*
  1346.      * setup environment (reflection) mapping.
  1347.      */
  1348.     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
  1349.     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
  1350.  
  1351.     /* scale texture image, make mipmaps and load texture
  1352.      *    gluBuild2DMipmaps( target, components, width, height,
  1353.      *        format,  type, imageArray ) 
  1354.      */
  1355.     gluBuild2DMipmaps(GL_TEXTURE_2D, 4, texWidth, texHeight,
  1356.              GL_RGBA, GL_UNSIGNED_BYTE, textureImage);
  1357.     glEndList();
  1358.     return( texList );
  1359. }
  1360.  
  1361. /* Build our own mipmaps using two different textures;
  1362.  * This function only works correctly if the two 
  1363.  * images are the same size.
  1364.  */
  1365. GLint initMipmapList( GLvoid )
  1366. {
  1367.     GLuint texList;
  1368.     int texWidth, texHeight;
  1369.     GLsizei sWidth, sHeight, w, h;
  1370.     GLubyte *mipmap, *source;
  1371.     GLuint  *image1, *image2;
  1372.     GLint level;
  1373.  
  1374.     image1 = rgbReadImageFile(TEXFILE1, &texWidth, &texHeight);
  1375.     image2 = rgbReadImageFile(TEXFILE2, &texWidth, &texHeight);
  1376.  
  1377.     printf("input image size: %dx%d\n", texWidth, texHeight);
  1378.  
  1379.     sWidth = nearestPower(texWidth);
  1380.     sHeight = nearestPower(texHeight);
  1381.  
  1382.     printf("scaled image size: %d %d\n", sWidth, sHeight);
  1383.  
  1384.     level = 0;
  1385.     w = sWidth;
  1386.     h = sHeight;
  1387.  
  1388.     texList = glGenLists(1);
  1389.     glNewList(texList, GL_COMPILE);
  1390.  
  1391.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  1392.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
  1393.             GL_NEAREST_MIPMAP_NEAREST);
  1394.     while (w >= 1)
  1395.     {
  1396.         printf("Defining mipmaps for level %d, size %dx%d\n", 
  1397.             level, w, h);
  1398.  
  1399.         mipmap = (GLubyte *)malloc(w * h * 4 * sizeof(GLubyte));
  1400.         if((level%2) == 0)
  1401.            source = (GLubyte *) image1;
  1402.         else
  1403.            source = (GLubyte *) image2;
  1404.  
  1405.         gluScaleImage(GL_RGBA, texWidth, texHeight, GL_UNSIGNED_BYTE,
  1406.               source, w, h, GL_UNSIGNED_BYTE, mipmap);
  1407.  
  1408.         glTexImage2D(GL_TEXTURE_2D, level, 4, w, h, 0, GL_RGBA,
  1409.               GL_UNSIGNED_BYTE, mipmap);
  1410.  
  1411.         w = w / 2;
  1412.         h = h / 2;
  1413.         level += 1;
  1414.     }
  1415.     glEndList();
  1416.  
  1417.     return( texList );
  1418. }
  1419.  
  1420. GLvoid resetEye( GLvoid )
  1421. {
  1422.     register int i;
  1423.  
  1424.     /* set visibleFlags for all shapes */
  1425.     for (i = 0; i < (TORUS+ 1); i++)
  1426.         visibleFlag[i] = GL_TRUE;
  1427.  
  1428.     initEye();
  1429. }
  1430.  
  1431.